#include <functional>
#include "TcpServer.h"
#include "NetMgr.h"


Acceptor::Acceptor(WorkerThreadN* eventLoop)
	: event_loop_(eventLoop)
{
	tcp_socket_.hSock = -1;
}

Acceptor::~Acceptor()
{

}

int Acceptor::Listen(std::string ip, uint16_t port)
{

	int ret = 0;
	do
	{
		
	/*	if (tcp_socket_.hSock > 0) {
			this->Close();
		}*/
		ret = tcp_socket_.Open(AfSockAddr(ip.c_str(), port));
		if (ret != 0)
		{
			break;
		}
		ret = tcp_socket_.Listen();
		if (ret != 0)
		{
			break;
		}
		channel_ptr_.reset(new Channel(tcp_socket_.hSock));


		channel_ptr_->SetReadCallback([this]() { this->OnAccept(); });
		channel_ptr_->EnableReading();
		event_loop_->UpdateChannel(channel_ptr_);

		//ChannelPtr channel = std::make_shared<Channel>(m_AfTcpSocket.hSock);

		//channel->SetReadCallback(std::bind(&TcpServer::OnConnect, this));

		//channel->EnableReading();

		//ret = netTask->UpdateChannel(channel);



		//port_ = port;
		//ip_ = ip;
		//is_started_ = true;

	} while (0);

	return ret;
}

void Acceptor::Close()
{
	if (tcp_socket_.hSock > 0) {
		event_loop_->RemoveChannel(channel_ptr_);
		tcp_socket_.Close();
	}
}

void Acceptor::OnAccept()
{
	AfTcpSocket peer;
	int r = this->tcp_socket_.Accept(&peer);
	if (0 == r)
	{
		if (new_connection_callback_) {
			new_connection_callback_(peer.hSock);
		}
		else {
			peer.Close();
		}
	}

}


TcpServer::TcpServer()
{
	//m_readBuffer.resize(1024 * 64);
}

TcpServer::~TcpServer()
{
}

bool TcpServer::Start(std::string ip, uint16_t port)
{
	int ret = 0;
	if (is_started_)
	{
		return true;
	}
	NetMgr::GetInstance()->Init();
	std::shared_ptr<WorkerThreadN> netTask = NetMgr::GetInstance()->m_oEventLoop.GetTaskScheduler();
	acceptor_ = std::make_unique<Acceptor>(netTask.get());

	acceptor_->SetNewConnectionCallback([this](socket_t sockfd) {

		TcpConnection::Ptr conn = this->OnConnect(sockfd);
		if (conn) {
			this->AddConnection(sockfd, conn);
			//conn->UpdateChannel();
			conn->SetDisconnectCallback([this](TcpConnection::Ptr conn) {
				WorkerThreadN* scheduler = conn->GetTaskScheduler();
				socket_t sockfd = conn->GetSocket();

				//conn->RemoveChannel();
				scheduler->PostTask([this, sockfd] {this->RemoveConnection(sockfd); });
				//if (!scheduler->PostTask([this, sockfd] {this->RemoveConnection(sockfd); })) {
					//scheduler->AddTimer([this, sockfd]() {this->RemoveConnection(sockfd); return false; }, 100);
				//}
				});

#if 0
			conn->SetReadCallback([this](std::shared_ptr<TcpConnection> conn, xop::BufferReader& buffer) {
				return this->OnRead(conn, buffer);


				});
#endif
		}
		});
	
	do 
	{
	
		ret = acceptor_->Listen(ip, port);
		if (ret != 0)
		{
			break;
		}
		port_ = port;
		ip_ = ip;
		is_started_ = true;

	} while (0);

	if (ret != 0)
	{
		return false;
	}
	return true;
}

void TcpServer::Stop()
{
	if (is_started_) {
		for (auto iter : connections_) 
		{
			iter.second->Close();
		}
		connections_.clear();
		acceptor_->Close();
	}
	is_started_ = false;
}

TcpConnection::Ptr TcpServer::OnConnect(socket_t hSock)
{

	std::shared_ptr<WorkerThreadN> netTask = NetMgr::GetInstance()->m_oEventLoop.GetTaskScheduler();

	TcpConnection::Ptr ptr = std::make_shared<TcpConnection>((WorkerThreadN*)netTask.get(), hSock);
	return ptr;

}

void TcpServer::AddConnection(SOCKET sockfd, TcpConnection::Ptr tcpConn)
{

	connections_.emplace(sockfd, tcpConn);
}

void TcpServer::RemoveConnection(SOCKET sockfd)
{
	connections_.erase(sockfd);
}


bool TcpServer::OnRead(TcpConnection::Ptr oTcpConnect, xop::BufferReader& buffer)
{
	std::string readData;
	int ret = buffer.ReadAll(readData);
	
	//int ret = oTcpConnect->Recv(m_readBuffer.data(), 1024*64);
	//if (ret < 0)
	//{
	//	oTcpConnect->RemoveChannel();
	//	int hSocket = oTcpConnect->GetSocket();
	//	connections_.erase(hSocket);
	//}
	if (ret > 0)
	{
		int ret_send = oTcpConnect->Send((char *)readData.c_str(), ret);
		printf("TcpServer Recv... ret:%d ret_send:%d \n", ret, ret_send);
		return true;
	}
	return false;
}


void TcpConnection::HandleRead()
{
	printf("Recv... ret: ret_send: \n");

	if (is_closed_) {
		return;
	}

	int ret = read_buffer_->Read(m_AfTcpSocket.hSock);
	if (ret > 0)
	{
		if (read_cb_)
		{
			read_cb_(shared_from_this(), *read_buffer_);
		}

	}
	if (ret < 0)
	{
		//if (disconnect_cb_)
		//{
		//	disconnect_cb_(shared_from_this());
		//}
		this->Close();
		printf("error .... \n");
	}
}

void TcpConnection::HandleClose()
{
	this->Close();
}
void TcpConnection::HandleError()
{
	this->Close();
}